package utils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 树形工具类
 * @author bug-fsh
 */
public class TreeUtils{

    private final static int ROOT_PARENT_ID = 0;
    private final static String ID_FIELD = "id";
    private final static String PARENT_ID_FIELD = "parentId";
    private final static String CHILDREN_FIELD = "children";

    /**
     * 通过所有节点获取所有树形结构
     * @param nodes
     * @return
     */
    public static <T> List<T> getTrees(List<T> nodes) {
        List<T> rootNodes = new ArrayList<T>();
        ReflectUtils<T> reflectUtils = null;
        if (!CollectionUtils.isEmpty(nodes)) {
            Iterator<T> iterator = nodes.iterator();
            T node = nodes.get(0);
            try {
                reflectUtils = new ReflectUtils<T>((Class<T>) node.getClass());
                while (iterator.hasNext()){
                    node = iterator.next();
                    int parentId = Integer.valueOf(reflectUtils.getValueByFieldName(node, PARENT_ID_FIELD).toString());
                    if (parentId == ROOT_PARENT_ID) {
                        rootNodes.add(node);
                        iterator.remove();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (!CollectionUtils.isEmpty(rootNodes) && !CollectionUtils.isEmpty(nodes)) {
            for (T rootNode : rootNodes) {
                constructTree(rootNode, nodes, reflectUtils);
            }
        }
        return rootNodes;
    }

    /**
     * 为根节点构造一颗树
     * @param rootNode
     * @param nodes
     * @param reflectUtils
     * @param <T>
     */
    public static <T>void constructTree(T rootNode, List<T> nodes, ReflectUtils<T> reflectUtils) {
        List<T> children = (List<T>) reflectUtils.getValueByFieldName(rootNode, CHILDREN_FIELD);
        Iterator<T> iterator = nodes.iterator();
        while (iterator.hasNext()) {
            T node = iterator.next();
            int id = Integer.valueOf(reflectUtils.getValueByFieldName(rootNode, ID_FIELD).toString());
            int parentId = Integer.valueOf(reflectUtils.getValueByFieldName(node, PARENT_ID_FIELD).toString());
            if (id == parentId) {
                children.add(node);
                iterator.remove();
            }
        }
        if (!CollectionUtils.isEmpty(children) && !CollectionUtils.isEmpty(nodes)) {
            for (T node : children) {
                constructTree(node, nodes, reflectUtils);
            }
        }
    }

    //单元测试
    public static void main(String [] args) throws Exception {
        /*
        List<Depart> list = new ArrayList<Depart>();
        list.add(new Depart(1, "技术部", 0));
        list.add(new Depart(2,"后端部门", 1));
        list.add(new Depart(3, "前端部门", 1));
        list.add(new Depart(4, "php部门", 2));
        list.add(new Depart(5,"java部门", 2));
        list.add(new Depart(6, "H5部门", 3));
        list.add(new Depart(7, "运营部", 0));
        list.add(new Depart(8,"运营部门1", 7));
        list.add(new Depart(9, "运营部门2", 7));
        List<Depart> trees = getTrees(list);
        */
        Depart depart = new Depart(1, "技术部", 0);
        ReflectUtils<Depart> reflectUtils = new ReflectUtils<Depart>(Depart.class);
        System.out.println(reflectUtils.objectToMap(depart));
    }
}

/**
 * 测试类
 */
class Depart {
    int id;
    String name;
    int parentId;
    List<Depart> children = new ArrayList<Depart>();

    public Depart(int id, String name, int parentId) {
        this.id = id;
        this.name = name;
        this.parentId = parentId;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getParentId() {
        return parentId;
    }

    public void setParentId(int parentId) {
        this.parentId = parentId;
    }

    public List<Depart> getChildren() {
        return children;
    }

    public void setChildren(List<Depart> children) {
        this.children = children;
    }
}
